<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>5.发布订阅模式</title>
</head>
<body>
发布订阅模式又叫观察者模式，定于对象间的一种一对多的依赖关系，当一个对象的状态发生改变时，所有依赖于它的对象都将得到通知
</body>
<script type="text/javascript">
	document.body.addEventListener('click',function(){
		alert(2);
	},false);
	// document.body.click();


	/* 自定义事件 */
	var Event = (function(){
		var global = this,
			Event,
			_default = 'default';

		Event = function(){
			var _listen,
				_trigger,
				_remove,
				_slice = Array.prototype.slice,
				_shift = Array.prototype.shift,
				_unshift = Array.prototype.unshift,
				namespaceCache = {},
				_create,
				find,
				each = function(arr,fn){
					var ret;
					for (var i = 0,len = arr.length; i < len; i++) {
						var n = arr[i];
						ret = fn.call(n,i,n);
					}
					return ret
				};
				_listen = function (key,fn,cache){
					if(!cache[key]){
						cache[key] = []
					}
					cache[key].push(fn);
				};
				_remove = function(key,cache,fn){
					if(cache[key]){
						if(fn){
							for(var i = cache[key].length;i >=0; i--){
								if(cache[key] === fn){
									cache[key].splice(i,1);
								}
							}
						}else{
							cache[key] = [];
						}
					}
				};
				_trigger = function(){
					var cache = _shift.call(arguments),
						key = _shift.call(arguments),
						args = arguments,
						_self = this,
						ret,
						stack = cache[key];
					if(!stack || !stack.length){
						return false;
					}
					return each(stack,function(){
						return this.apply(_self,args);
					});
				};

				_create = function(namespace){
					var namespace = namespace || _default;
					var cache = {},
						offlineStack = [],
						ret = {
							listen : function(key,fn,last){
								_listen(key,fn,cache);
								if(offlineStack === null){
									return;
								}
								if(last === 'last'){
									offlineStack.length && offlineStack.pop()();
								}else{
									each(offlineStack,function(){
										this();
									});
								}
								offlineStack = null;
							},
							one : function(key,fn,last){
								_remove(key,cache);
								this.listen(key,fn,last);
							},
							remove : function(key,fn){
								_remove(key,cache,fn);
							},
							trigger:function(){
								var fn,
									args,
									_self = this;
								_unshift.call(arguments,cache);
								args = arguments;
								fn = function(){
									return _trigger.apply(_self,args);
								};
								if(offlineStack){
									return offlineStack.push(fn);
								}
								return fn();
							}ac
					};
					return namespace ? (namespaceCache[namespace] ? namespaceCache[namespace] : namespaceCache[namespace] = ret ) : ret
			};

			return {
				create : _create,
				one : function(key,fn,last){
					var event = this.create();
						event.one(key,fn,last);
				},
				remove : function(key,fn){
					var event = this.create();
						event.remove(key,fn);
				},
				listen : function(key,fn,last){
					var event = this.create();
						event.listen(key,fn,last);
				},
				trigger:function(){
					var event = this.create();
						event.trigger.apply(this,arguments);
				}

			};
		}();
		return Event;
	})();


	/* 先发布后订阅 */
	// Event.trigger('click',1);
	// Event.listen('click',function(a){
	// 	console.log(a);
	// });

	/* 使用命名空间 */
	// Event.create('namespace1').listen('click',function(a){
	// 	console.log(a);
	// })
	// Event.create('namespace1').one('click',function(a){
	// 	console.log(a);
	// })
	Event.create('namespace1').trigger('click',1);
	Event.create('namespace1').trigger('click',1);



	// Event.create('namespace2').listen('click',function(a){
	// 	console.log(a);
	// })
	// Event.create('namespace2').trigger('click',2);




</script>
</html>